home *** CD-ROM | disk | FTP | other *** search
/ PC World 2006 November / PCWorld_2006-11_cd.bin / domacnost a kancelar / findgraph / fgraph.exe / {app} / ApprSource / poli_n.cpp < prev    next >
C/C++ Source or Header  |  2005-08-29  |  12KB  |  504 lines

  1. /******************************************************************************
  2.  * Plug-In DLL Example and Template
  3.  * for use with C/C++
  4.  *
  5.  * Compile DLL with any name.
  6.  * Place it in  the program FindGraph subfolder "Appr".
  7.  * Next functions must be exported:
  8.  *        MaxOfFactors
  9.  *        Prepare
  10.  *        CalcInPoint
  11.  *        FunctionTitle
  12.  *        FunctionName 
  13.  *        FunctionString
  14.  *        ParamInfo
  15.  * 
  16.  * To test DLL, restart FundGraph, 
  17.  * start The Wizard of approximation,
  18.  * on step 2 select 'User defined function'.
  19.  * If all right, on step 3 your function will appear in list.
  20.  * 
  21.  ******************************************************************************/
  22.  
  23.  
  24. #include <windows.h>
  25. #include <tchar.h>
  26. #include <math.h>
  27. #include "poli_n.h"
  28.  
  29.  
  30. #include <stdio.h>
  31.  
  32.  
  33. // 
  34. #pragma comment(linker,"/MERGE:.rdata=.text")
  35. #pragma comment(linker,"/FILEALIGN:512 /SECTION:.text,EWRX /IGNORE:4078")
  36.  
  37. //////////////////////////////////////////////////////////////////////////////////
  38.  
  39.  
  40. HINSTANCE g_hInstance=NULL;
  41. BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
  42. {
  43.     switch (ul_reason_for_call)
  44.     {
  45.         case DLL_PROCESS_ATTACH:
  46.              g_hInstance = (HINSTANCE )hModule;
  47.              break;
  48.         case DLL_PROCESS_DETACH:
  49.              break;
  50.     }
  51.      return TRUE;
  52. }
  53.  
  54.  
  55.  
  56.  
  57. ////////////////////////////////////////////////////////////////////////////////////////////////////
  58. #define N_FACTORS 18 
  59. #define aa(i,j) pfs[i*nn+j]
  60.  
  61.  
  62. // calc f**n
  63. double PowInt( double f, int n)
  64.   double val=1.;
  65.   if  ( n ) for ( int i=1; i<=n; i++ )
  66.          val *= f;
  67.   return val;
  68. }
  69.  
  70.  
  71. // Calc line equations
  72. // nAppr - number equations
  73. // fs - coeffs. matrix aa(i,j)
  74. // fu - buffer to return results
  75. //
  76. void CalcEquGauss(UINT  nAppr, double *pfs, double *pfu)
  77. {
  78.   int   i, j, k,
  79.          n = nAppr,
  80.         nn = n+2;
  81.  
  82.   for (i=0; i <= n; i++)
  83.   {
  84.     for (k=n+1; k >= i; k--)
  85.          aa(i,k) /= aa(i,i);
  86.     if  (i < n)
  87.       for (j=i+1; j <= n; j++)
  88.         for (k=n+1; k >= 0; k--)
  89.              aa(j,k) -= (aa(j,i)*aa(i,k));
  90.   }
  91.  
  92.   pfu[n] = aa(n,n+1);
  93.   if  (n)
  94.   for (i=n-1; i >= 0; i-- )
  95.     for (k=i+1, pfu[i] = aa(i,n+1); k<= n; k++)
  96.              pfu[i] -= (aa(i,k)*pfu[k]);
  97. }
  98.  
  99.  
  100. // return number points with u != fNullU
  101. //
  102. int FindLimits(double &fMinU, double &fMaxU, double &fMinV, double &fMaxV,
  103.                double *pfU, double *pfV, int nPoints, double fNullU)
  104. {
  105.     int  np = 0;
  106.     for (int i=0; i<nPoints; i++)
  107.     {
  108.         double u = pfU[i],
  109.                v = pfV[i];
  110.         if  (fNullU == u) continue;
  111.         if  (np==0)
  112.         {
  113.             fMinU = fMaxU = u;
  114.             fMinV = fMaxV = v;
  115.         }
  116.         else
  117.         {
  118.             if (fMinU > u) fMinU = u;
  119.             if (fMaxU < u) fMaxU = u;
  120.             if (fMinV > v) fMinV = v;
  121.             if (fMaxV < v) fMaxV = v;
  122.         }
  123.         np++;
  124.     }
  125.     return np;
  126. }
  127.  
  128.  
  129.  
  130. //-------------------------------------------
  131. // Error of calculus
  132. //
  133. double CalcError(double *pfU, double *pfV, int nPoints, 
  134.                  double *pfFactors, int nFactors)
  135. {
  136.     if (nPoints  <= 0)
  137.         return 0.;
  138.     double fError = 0.;
  139.     for (int id=0; id < nPoints; id++ )
  140.     {
  141.         double u = pfU[id],
  142.                v = pfV[id],
  143.                v1= CalcInPoint(u, pfFactors, nFactors);
  144.         fError += (v1-v)*(v1-v);
  145.     }
  146.     fError = sqrt(fError/nPoints);
  147.     return fError;
  148. }
  149.  
  150. ////////////////////////////////////////////////////////////////////////////////////////////////////
  151. //
  152. // Return the number of factors (see function 'Prepare')
  153. // use to memory allocate for pfFactors
  154. //
  155.  
  156. //extern "C" bool __declspec( dllexport ) __stdcall TransFromDisk(char *Base, char *Disk);
  157.  
  158.  
  159. int __declspec(dllexport) __stdcall MaxOfFactors()
  160. {
  161.     return N_FACTORS;
  162. }
  163.  
  164.  
  165. //
  166. // Prepare approximation function V(U) = Function(U)
  167. //     V(U) = V0 + (U-U0)^M*(A0 + A1*U + ... +AN*U^N)
  168. // Input:
  169. // Array of points (U,V)
  170. //        fMinU, fMaxU - limits of U 
  171. //        fMinV, fMaxV - limits of V 
  172. //        pfU, pfV - array of nPoints points (U,V)
  173. //        pfW         - weight of point
  174. //      nPoints     - number of points in array 
  175. // Parameters:
  176. //        pfParams - array of parameters
  177. //        M  = pfParams[0] - pow of 
  178. //        N  = pfParams[1] - pow of polinom approximation
  179. //        U0 = pfParams[2]
  180. //        V0 = pfParams[3]
  181. //      nParams  - number of parameters in array 
  182. //
  183. // Output:
  184. // Array of factors is calculated.
  185. // This factors will be used in function CalcInPoint(U, pfFactors)
  186. //        pfFactors - array of factors, defined by user
  187. //        Notes: pfFactors[*pnFactors-1] = Error of calculus
  188. //      nFactors:
  189. //            Input  - maximum possible number of factors in array 
  190. //
  191. // return: number of factors if success, else error code
  192. //
  193. int __declspec(dllexport) __stdcall Prepare (double fMinU, double fMaxU, double fMinV, double fMaxV,
  194.                double *pfU, double *pfV, double *pfW, int nPoints, 
  195.                double *pfParams , int nParams ,
  196.                double *pfFactors, int nFactors)
  197. {
  198.     int nResult = 0;
  199.     if (nPoints < 2) // not enough points
  200.         return -1;
  201.  
  202.     if (nFactors < N_FACTORS) // not enough memory for result
  203.         return -2;
  204.  
  205.  
  206.     double fPoli = 1;
  207.     int    nAppr = 4;
  208.     double fU0   = 0,
  209.            fV0     = 0;
  210.  
  211.     if (nParams > 0) fPoli =      pfParams[0];
  212.     if (nParams > 1) nAppr = (int)pfParams[1];
  213.     if (nParams > 2) fU0   =      pfParams[2];
  214.     if (nParams > 3) fV0   =      pfParams[3];
  215.  
  216.  
  217.     if (fPoli <-5) fPoli =-5;    if (fPoli > 5) fPoli = 5;
  218.     if (nAppr < 0) nAppr = 0;    if (nAppr > 5) nAppr = 5;
  219.  
  220.  
  221.     int nPointInAppr = FindLimits(fMinU, fMaxU, fMinV, fMaxV, pfU, pfV, nPoints, fU0);
  222.     double dU = fMaxU - fMinU;
  223.     if (dU <  0.) dU = -dU;
  224.  
  225.     if (nPointInAppr < 5)
  226. //           nAppr = nPointInAppr;
  227.            nAppr = nPointInAppr-1;
  228.  
  229.     int    nn = nAppr + 2,
  230.            ns =(nAppr+1)*(nn+1);
  231.  
  232.     // nAppr < 5
  233.     double fAppr[10];
  234.  
  235.     double 
  236.            *pfs,
  237.            *pfu;
  238.     // use: aa(i,j) == pfs[i*nn+j]
  239.  
  240.     pfu = new double[nAppr+1+nPoints];//use as normed fU and coeff
  241.     pfs = new double[ns];
  242.     memset(pfs, 0, ns*sizeof(double));
  243.  
  244.         int id, i, j;
  245.         int  nSum = 0; // point with U>0, V>0
  246.         for (id=0; id < nPoints; id++ )
  247.         {
  248.             pfu[id] = pfU[id] / dU;
  249.             nSum++;
  250.         }
  251.  
  252.         for (i=0; i <= nAppr; i++ )//equation coeffs
  253.         {
  254.             for (j=0; j <= nAppr+1; j++ )  aa(i,j) = 0.;
  255.  
  256.             for (id=0; id < nPoints; id++ )
  257.             {
  258.                 double  u = pfU[id],
  259.                         v;
  260.                 if  (u != fU0)
  261.                 {
  262.                     v = (pfV[id] - fV0) / pow(u-fU0, fPoli);
  263.                     for (j=0; j <= nAppr; j++ )
  264.                         aa(i, j) += (pfW[id] * PowInt(pfu[id], i+j));
  265.  
  266.                     aa(i, nAppr+1) += (pfW[id] * PowInt(pfu[id], i) * v);
  267.                 }
  268.             } 
  269.         }
  270.         CalcEquGauss(nAppr, pfs, pfu);
  271.         for (i=0; i<= nAppr; i++ )
  272.         {
  273.             fAppr[i] = pfu[i] / PowInt(dU, i);
  274.         }
  275.  
  276.         nResult         = N_FACTORS;
  277.         
  278.         pfFactors[0] = nSum;
  279.         pfFactors[1] = fMinU; pfFactors[2] = fMaxU; // Unused now - reserved
  280.         pfFactors[3] = fMinV; pfFactors[4] = fMaxV; // Unused now - reserved
  281.         pfFactors[4] = 0; // Unused now - reserved
  282.         pfFactors[5] = fU0;
  283.         pfFactors[6] = fV0;
  284.         pfFactors[7] = fPoli;
  285.         pfFactors[8] = nAppr;
  286.         for (i=0; i<=nAppr; i++)
  287.             pfFactors[9+i] = fAppr[i];
  288.     
  289.         pfFactors[N_FACTORS-1] = CalcError(pfU, pfV, nPoints, pfFactors, nFactors); 
  290.  
  291.     delete [] pfu;
  292.     delete [] pfs;
  293.     
  294.     return nResult;
  295. }
  296.  
  297.  
  298.  
  299.  
  300. // Calculate value V = Function(fU)
  301. // Input:
  302. //        fU
  303. //        pfFactors - array of factors, prepared in finction Prepare()
  304. //      pnFactors: - number of factors in array 
  305. //
  306. // return: value calculated
  307. //
  308. double __declspec(dllexport) __stdcall CalcInPoint(double fU, 
  309.                                          double *pfFactors, int nFactors)
  310. {
  311.     if (nFactors < N_FACTORS)
  312.         return  0.;
  313.     double 
  314.             U     = fU,
  315.             U0    = pfFactors[5],
  316.             V0    = pfFactors[6],
  317.              fPoli = pfFactors[7];
  318.     int nAppr = (int)pfFactors[8];
  319.  
  320.     if (fPoli <-5) fPoli =-5;
  321.     if (fPoli > 5) fPoli = 5;
  322.     if (nAppr < 0) return 0.;
  323.  
  324.     double f = 1.,
  325.            fV= 0.;
  326.     for (int i=0; i<=nAppr; i++)
  327.     {
  328.         fV += f*pfFactors[9+i];
  329.         f *= U;
  330.     }
  331.  
  332.     fV = V0 + fV * pow(U-U0, fPoli);
  333. //    fV = V0 + (U-U0)*(A0 + A1*U);
  334. //    fV = (A0 + A1*U + A2*U*U);
  335.     return fV;
  336. }
  337.  
  338. // Fill information string with name of approximation method
  339. // It is used in FindGraph <Master of approximations page 2><list of user defined functions>
  340. // for example - "User's poli_n"
  341. // Input:
  342. //        pstr - buffer TCHAR
  343. //      nMaxLength - maximum buffer length
  344. //
  345. // Output:
  346. //        pstr - name of approximation method
  347. //
  348. // return: string length if success, else -1
  349. //
  350. int __declspec(dllexport) __stdcall FunctionTitle(LPTSTR pstr, int nMaxLength) 
  351. {
  352.     if (pstr==0)
  353.         return -1;
  354.     lstrcpyn(pstr, TEXT(" y = V0 + (x-U0)^M *(A0 + A1*x...+AN*x^N)"), nMaxLength);
  355.     return lstrlen(pstr);
  356. }
  357.  
  358.  
  359.  
  360. // Fill information string with name of approximation function
  361. // for example - "V(U) = V0 + Exp(a*(U-U0))*Pow((U-U0), b)"
  362. // It is used in FindGraph <Master of approximations page 3><Function description>
  363. // Input:
  364. //        pstr - buffer TCHAR
  365. //      nMaxLength - maximum buffer length
  366. //
  367. // Output:
  368. //        pstr - name of approximation function
  369. //
  370. // return: string length if success, else -1
  371. //
  372. int __declspec(dllexport) __stdcall FunctionName(LPTSTR pstr, int nMaxLength) 
  373. {
  374.     if (pstr==0)
  375.         return -1;
  376.     lstrcpyn(pstr, TEXT("f(U) = V0 + (U-U0)^M *(A0+...+AN*U^N)"), nMaxLength);
  377.     return lstrlen(pstr);
  378. }
  379.  
  380.  
  381.  
  382. // Fill information string with formula of calculated function f(U) = Formula()
  383. // It is used in FindGraph <Master of approximations pages 4 and 5>
  384. // Input:
  385. //        pstr - buffer TCHAR
  386. //      nMaxLength - maximum buffer length
  387. //        pfFactors - array of factors, prepared in finction Prepare()
  388. //      pnFactors: - number of factors in array 
  389. //
  390. // Output:
  391. // pstr - string of calculated function f(U)
  392. //
  393. // return: string length if success, else -1
  394. //
  395. int __declspec(dllexport) __stdcall FunctionString(double *pfFactors, int nFactors,
  396.                                          LPTSTR pstr, int nMaxLength) 
  397. {
  398.     if (pstr==0)
  399.         return -1;
  400.     if (nFactors < N_FACTORS)
  401.         return -2;
  402.  
  403.     TCHAR  sz[256];
  404.     double 
  405.             U0     = pfFactors[5],
  406.             V0     = pfFactors[6],
  407.              fPoli= pfFactors[7],
  408.             fA[10];
  409.  
  410.     int  nAppr = (int)pfFactors[8];
  411.     if  (nAppr>=0)
  412.     for (int i=0; i<=nAppr; i++)
  413.     {
  414.         fA[i] = pfFactors[9+i];
  415.     }
  416.  
  417.  
  418. //    sprintf(sz, TEXT("f(U) = %4.4g + (U-%4.4g)*(%4.4g + %4.4g*U + %4.4g*U2)"),V0, U0, A0, A1, A2);
  419. //    sprintf(sz, TEXT("f(U) = %4.4g + (U-%4.4g)*(%4.4g + %4.4g*U)"),V0, U0, A0, A1);
  420.     TCHAR sz1[24], sz2[24],
  421.           sza[256]; lstrcpy(sza, TEXT(""));
  422.  
  423.     if  (nAppr>=0)
  424.     for (int i=0; i<=nAppr; i++)
  425.     {
  426.         TCHAR szn[24]; 
  427.         sprintf(szn, TEXT("%4.4g"), fA[i]);
  428.         if (fA[i] > 0. && i)
  429.             lstrcat(sza, "+");
  430.         if (fA[i] != 0.)
  431.         {
  432.             lstrcat(sza, szn);
  433.             sprintf(szn, TEXT("*U^%1d"), i);
  434.             if (i)
  435.                 lstrcat(sza, szn);
  436.         }
  437.     }
  438.  
  439.     if (V0 != 0) sprintf(sz1, "%4.4g + ", V0);
  440.     else         lstrcpy(sz1, TEXT(""));
  441.  
  442.     if (U0 != 0) sprintf(sz2, "(U-%4.4g)", U0);
  443.     else         lstrcpy(sz2, TEXT("U"));
  444.  
  445.     if (fPoli==1) // default
  446.         sprintf(sz, TEXT("f(U) = %s%s * (%s)"),sz1, sz2, sza);
  447.     else
  448.         sprintf(sz, TEXT("f(U) = %s%s^%3.1f * (%s)"),sz1, sz2, fPoli, sza);
  449.  
  450. //TCHAR szz[64]; sprintf(szz,"\nM=%d N=%d",(int)fPoli, nAppr); lstrcat(sz, szz);    
  451.  
  452.     lstrcpyn(pstr, sz, nMaxLength);
  453.     return lstrlen(pstr);
  454. }
  455.  
  456.  
  457.  
  458. // Fill information string with name of parameter and it's default value
  459. // It is used in FindGraph <Master of approximations page 3>
  460. // Input:
  461. //      nParam - number of edit box in page 3
  462. //                 1, 2, 3, 4
  463. //               see list of pfParams in function 'Prepare'
  464. //        pstr - buffer TCHAR
  465. //      nMaxLength - maximum buffer length
  466. //
  467. // Output:
  468. //        pstr - name of parameter[nParam]
  469. //      pfDefault - default value of parameter[nParam]
  470. //
  471. // return: string length if success, else -1
  472. //
  473. int __declspec(dllexport) __stdcall ParamInfo(int nParam, LPTSTR pstr, int nMaxLength, double *pfDefault) 
  474. {
  475.     if (pstr==0)
  476.         return -1;
  477.     switch (nParam)
  478.     {
  479.         case 1: 
  480.             lstrcpyn(pstr, TEXT("M"), nMaxLength);
  481.             if (pfDefault != NULL)
  482.                *pfDefault = 1.;
  483.             break;
  484.         case 2: 
  485.             lstrcpyn(pstr, TEXT("N"), nMaxLength);
  486.             if (pfDefault != NULL)
  487.                *pfDefault = 4.;
  488.             break;
  489.         case 3: 
  490.             lstrcpyn(pstr, TEXT("U0"), nMaxLength);
  491.             if (pfDefault != NULL)
  492.                *pfDefault = 0.;
  493.             break;
  494.         case 4: 
  495.             lstrcpyn(pstr, TEXT("V0"), nMaxLength);
  496.             if (pfDefault != NULL)
  497.                *pfDefault = 0.;
  498.             break;
  499.         default: return -1;
  500.     }
  501.     return lstrlen(pstr);
  502. }
  503.